/* s^2 - test the sHT_streq function
   Copyright (C) 2019 Ariadne Devos

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#include <sHT/string.h>
#include <string.h>
#include <stdio.h>

/* Test a few special cases -- code that uses memeq and streq must come
  with their own tests, which supplements these.

  Symmetric cases are automatically generated, and the expected values are
  scrambled. */
static const struct {
	const char *a;
	const char *b;
	size_t length;
	size_t expect;
} cases[] = {
	/* It should not be accessed, because that's unnecessary
	   -- it is allowed, however. */
	{ .a = (char *) -1, .b = (char *) -2, .length = 0, .expect = 0 },
	/* zero-length */
	{ .a = "", .b = "a", .length = 0, .expect = 0},
	/* don't be afraid of NUL */
	{ .a = "", .b = "a", .length = 1, .expect = 1 },
	{ .a = "", .b = "", .length = 1, .expect = 0 },
	{ .a = "\0a", .b = "\0b", .length = 2, .expect = 1 },
	{ .a = "\0a", .b = "\0b\xff", .length = 2, .expect = 1 },
	/* longer test cases -- exercise word-at-a-time implementations a little */
	{ .a = "abcdefg\x00""abcdefg\x11", "abcdefg\x00""abcdefg\x11", .length = 16, .expect = 0 },
	{ .a = "abcdefg\x00""abcdefg\x11""0", "abcdefg\x00""abcdefg\x11""0", .length = 17, .expect = 0 },
	{ .a = "abcdefg\x00""abcdefg\x11", "abcdefg\x00""abcdefg\x12", .length = 16, .expect = 1 },
	{ .a = "abcdefg\x00""abcdefg\x11""0", "abcdefg\x00""abcdefg\x11""1", .length = 17, .expect = 1 },
};

int
main(void)
{
	_Bool ioerr = 0;
	for (size_t i = 0; i < sizeof(cases)/sizeof(*cases); i++) {
		/* test the test case */
		if (!!memcmp(cases[i].a, cases[i].b, cases[i].length) != cases[i].expect)
			goto fail_testcase;

		if (sHT_memeq(cases[i].a, cases[i].b, 0, 1, cases[i].length) != cases[i].expect)
			goto fail;
		if (sHT_memeq(cases[i].b, cases[i].a, 0, 1, cases[i].length) != cases[i].expect)
			goto fail;
		if (sHT_memeq(cases[i].a, cases[i].b, 2000, 78, cases[i].length) != (cases[i].expect ? 78 : 2000))
			goto fail;
		if (sHT_memeq(cases[i].b, cases[i].a, 2000, 78, cases[i].length) != (cases[i].expect ? 78 : 2000))
			goto fail;
	}
	ioerr |= puts("PASS: memeq/special") < 0;
	ioerr |= puts("PASS: memeq/equi-stdlib") < 0;
	return ioerr ? 2 : 0;

fail:
	ioerr |= puts("FAIL: memeq/special") < 0;
	ioerr |= puts("SKIP: memeq/equi-stdlib") < 0;
	return ioerr ? 2 : 1;

fail_testcase:
	ioerr |= puts("FAIL: memeq/equi-stdlib") < 0;
	ioerr |= puts("SKIP: memeq/special") < 0;
	return ioerr ? 2 : 1;
}
